/* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
/* Copyright (C) 2012 Zongyou Yao. All rights reserved.     */

#include <stddef.h>
#include "assert.h"
#include "mem.h"
#include "stack.h"

struct stack_t {
    int count;
    struct elem {
        void *x;
        struct elem *link;
    } *head;
};

stack_t stack_new(void)
{
    stack_t stack;
    NEW(stack);
    stack->count = 0;
    stack->head = NULL;
    return stack;
}

int stack_empty(stack_t stack)
{
    assert(stack);
    return stack->count == 0;
}

void stack_push(stack_t stack, void *x)
{
    struct elem *t;
    assert(stack);
    NEW(t);
    t->x = x;
    t->link = stack->head;
    stack->head = t;
    stack->count++;
}

void * stack_pop(stack_t stack)
{
    void *x;
    struct elem *t;
    assert(stack);
    assert(stack->count > 0);
    t = stack->head;
    stack->head = t->link;
    stack->count--;
    x = t->x;
    FREE(t);
    return x;
}

void stack_free(stack_t *stack)
{
    struct elem *t, *u;
    assert(stack && *stack);
    for (t = (*stack)->head; t; t = u) {
        u = t->link;
        FREE(t);
    }
    FREE(*stack);
}
